﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Styx;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Styx.Pathing;
using Styx.Common;
using System.Windows.Media;
using Styx.CommonBot.Frames;
using System.Diagnostics;


namespace Guardian
{
    public partial class Combat : CombatRoutine
    {

        public override string Name { get { return "Feral + Guardian by Pasterke"; } }
        public override WoWClass Class { get { return WoWClass.Druid; } }
        public LocalPlayer Me { get { return StyxWoW.Me; } }

        public override Composite CombatBehavior { get { return CreateCombat(); } }
        public override Composite PreCombatBuffBehavior { get { return CreatePreCombatBuffs(); } }
        public override Composite PullBehavior { get { return CreatePullBehavior(); } }
        public override Composite RestBehavior { get { return CreateRestBehavior(); } }
        public override Composite PullBuffBehavior { get { return CreatePullBuffBehavior(); } }
        public override Composite CombatBuffBehavior { get { return CreateCombatBuffs(); } }

        string LastSpell = string.Empty;

        public override bool WantButton { get { return true; } }
        public override void OnButtonPress()
        {
            Form1 ConfigForm = new Form1();
            ConfigForm.ShowDialog();
        }

        public string usedBot { get { return BotManager.Current.Name.ToUpper(); } }

        public override void Pulse()
        {
            try
            {
                if (Me.IsDead && AutoBot)
                {
                    Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                }
                if (Me.ZoneId == 6757 && CanBuffEat && SettingsCommon.myPrefs.AutoTimelessIsleBuffs)
                {
                    checkBuffs();
                }
                /*if (!Me.Combat && (usedBot.Contains("QUEST") || usedBot.Contains("GRIND")) && Lootables.Count() >= 1)
                {
                    GetLoot();
                }*/
                return;
            }
            catch { }
        }

        public override void Initialize()
        {
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
            EventHandlers.AttachCombatLogEvent();
        }

        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }

        Composite CreateRestBehavior()
        {
            return new PrioritySelector(
            new Decorator(ret => AutoBot 
                && Me.HealthPercent <= SettingsCommon.myPrefs.PercentEatFood 
                && !Me.IsSwimming, EatFood()),
            Cast(HEALING_TOUCH, ret => AutoBot
                && SpellManager.HasSpell(HEALING_TOUCH) 
                && Me.HealthPercent <= SettingsCommon.myPrefs.PercentHealingTouch 
                && !Me.HasAura("Drink") 
                && !Me.HasAura("Food")),
            Cast(REJUVENATION, ret => AutoBot
                && SpellManager.HasSpell(REJUVENATION) 
                && !Me.HasAura(REJUVENATION) 
                && Me.HealthPercent <= SettingsCommon.myPrefs.PercentRejuvenation 
                && !Me.HasAura("Drink") && !Me.HasAura("Food"))
                );
        }

        Composite CreatePreCombatBuffs()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                new Decorator(ret => CanBuffEat && Me.IsSwimming && Me.Shapeshift != ShapeshiftForm.Aqua,
                    new Action(ret => { SpellManager.Cast("Aquatic Form"); return RunStatus.Failure; })),
                new Decorator(ret => CanBuffEat
                    && !Me.HasAura(MOTW)
                    && !Me.HasAura("Blessing of Kings")
                    && !Me.HasAura("Legacy of the Emperor")
                    && nextBuffAllowed <= DateTime.Now, MarkOfTheWild()),
                new Decorator(ret => CanBuffEat
                    && SettingsCommon.myPrefs.AutoUseAlchemyFlask
                    && nextBuffAllowed <= DateTime.Now
                    && !HaveFlaskBuff
                    && !buffExists("Enhanced Agility", Me)
                    && !buffExists(CRYSTAL_OF_INSANITY_BUFF, Me), AlchemyFlask()),
                new Decorator(ret => CanBuffEat
                    && !Me.CurrentMap.IsArena
                    && SettingsCommon.myPrefs.AutoUseCrystalOfInsanity
                    && nextBuffAllowed <= DateTime.Now
                    && !HaveFlaskBuff
                    && !buffExists(CRYSTAL_OF_INSANITY_BUFF, Me), CrystalOfInsanity()),
                new Decorator(ret => CanBuffEat && !Me.HasAura("Symbiosis") && SettingsBear.myPrefs.AutoSymbiosis && nextSymbiosisCastAllowed <= DateTime.Now, CastBearSymbiosis()),
                new Decorator(ret => CanBuffEat && !Me.HasAura("Symbiosis") && SettingsCat.myPrefs.AutoSymbiosis && nextSymbiosisCastAllowed <= DateTime.Now, CastCatSymbiosis())
                );
        }
        Composite CreateCombatBuffs()
        {
            return new PrioritySelector(
            new Decorator(ret => Paused, PauseCR()),
            new Decorator(ret => SpellManager.HasSpell(REJUVENATION)
                    && !Me.HasAura(REJUVENATION)
                    && SpellManager.CanCast(REJUVENATION)
                    && Me.HealthPercent <= SettingsCommon.myPrefs.PercentRejuCombat,
                    new Action(ret =>
                    {
                        SpellManager.Cast(REJUVENATION, Me);
                        Logging.Write(Colors.Pink, "Rejuvenation on Me");
                        return RunStatus.Failure;
                    })),
            new Decorator(ret => CanBuffEat
                    && SettingsCommon.myPrefs.AutoUseAlchemyFlask
                    && nextBuffAllowed <= DateTime.Now
                    && !HaveFlaskBuff && !buffExists("Enhanced Agility", Me)
                    && !buffExists(CRYSTAL_OF_INSANITY_BUFF, Me), AlchemyFlask()),
                new Decorator(ret => CanBuffEat
                    && SettingsCommon.myPrefs.AutoUseFlaskOfTheEarth != SettingsCommon.FlaskUse.Manual
                    && nextBuffAllowed <= DateTime.Now
                    && !HaveFlaskBuff, FlaskOfTheEarth()),
                new Decorator(ret => CanBuffEat
                    && SettingsCommon.myPrefs.AutoUseFlaskOfSpringBlossom != SettingsCommon.FlaskUse.Manual
                    && nextBuffAllowed <= DateTime.Now
                    && !HaveFlaskBuff, FlaskOfSpringBlossom()),
                new Decorator(ret => CanBuffEat
                    && !Me.CurrentMap.IsArena
                    && SettingsCommon.myPrefs.AutoUseCrystalOfInsanity
                    && nextBuffAllowed <= DateTime.Now
                    && !HaveFlaskBuff
                    && !buffExists(CRYSTAL_OF_INSANITY_BUFF, Me), CrystalOfInsanity()),
                new Decorator(ret => CanBuffEat
                    && !Me.HasAura(MOTW)
                    && !Me.HasAura("Blessing of Kings")
                    && !Me.HasAura("Legacy of the Emperor")
                    && nextBuffAllowed <= DateTime.Now, MarkOfTheWild())
                );
        }
        Composite CreatePullBuffBehavior()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                Cast(CAT_FORM, ret => Me.Specialization == WoWSpec.None && SpellManager.HasSpell(CAT_FORM) && Me.Shapeshift != ShapeshiftForm.Cat),
                Cast(CAT_FORM, ret => Me.Specialization == WoWSpec.DruidFeral && Me.Shapeshift != ShapeshiftForm.Cat),
                Cast(BEAR_FORM, ret => Me.Specialization == WoWSpec.DruidGuardian && Me.Shapeshift != ShapeshiftForm.Bear)
                );
        }
        Composite CreatePullBehavior()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                new Decorator(ret => IsRooted(Me), RemoveRooted()),
                new Decorator(ret => gotTarget && nextPullSpellAllowed <= DateTime.Now, PullSpells()),
                new Decorator(ret => gotTarget && AllowMovement && !Me.CurrentTarget.IsWithinMeleeRange, CreateMovementBehavior()),
                new Decorator(ret => gotTarget && AllowMovement && Me.CurrentTarget.IsWithinMeleeRange && Me.IsMoving, CreateStopMovement()),
                new Decorator(ret => gotTarget && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget), FaceMyTarget())
                );
        }

        Composite CreateCombat()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                new Decorator(ret => Me.CurrentTarget != null && Me.CurrentTarget.IsDead, new Action(ret => { Me.ClearTarget(); return RunStatus.Failure; })),
                new Decorator(ret => IsRooted(Me), RemoveRooted()),
                new Decorator(ret => gotTarget 
                    && AutoBot 
                    && ((UnfriendlyUnits.Count() > 0 && Me.CurrentTarget.Distance >= 12) || Me.CurrentTarget.IsFriendly), 
                    new Action(ret => { Me.ClearTarget(); return RunStatus.Failure; })),
                new Decorator(ret => gotTarget && AllowMovement && !Me.CurrentTarget.IsWithinMeleeRange, CreateMovementBehavior()),
                new Decorator(ret => gotTarget && AllowMovement && Me.CurrentTarget.IsWithinMeleeRange && Me.IsMoving, CreateStopMovement()),
                new Decorator(ret => gotTarget && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget), FaceMyTarget()),
                new Decorator(ret => Me.Specialization == WoWSpec.None, LowbieRotation()),
                new Decorator(ret => Me.Specialization == WoWSpec.DruidGuardian || NeedBearForm, BeerRotation()),
                new Decorator(ret => Me.Specialization == WoWSpec.DruidFeral && !NeedBearForm, KatRotation())
                    );
        }

        #region buffs
        Composite MarkOfTheWild()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(MOTW))
                {
                    SpellManager.Cast(MOTW);
                    Logging.Write(Colors.BlanchedAlmond, MOTW);
                    SetNextBuffAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region pull
        private DateTime nextPullSpellAllowed;

        public void SetNextPullSpellAllowed()
        {
            nextPullSpellAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 2500);
        }
        Composite PullSpells()
        {
            return new Action(ret =>
            {
                if (gotTarget 
                    && !SpellManager.HasSpell(CAT_FORM) 
                    && SpellManager.CanCast(WRATH)
                    && IsInRange(38, Me.CurrentTarget))
                {
                    SpellManager.Cast(WRATH);
                    Logging.Write(Colors.LightBlue, WRATH);
                    SetNextPullSpellAllowed();
                    return RunStatus.Success;
                }
                if (gotTarget
                    && SpellManager.HasSpell(FAERIE_SWARM)
                    && GetSpellCooldown(FAERIE_SWARM).TotalSeconds < 1
                    && SpellManager.CanCast(FAERIE_SWARM)
                    && IsInRange(30, Me.CurrentTarget))
                {
                    SpellManager.Cast(FAERIE_SWARM);
                    Logging.Write(Colors.LightBlue, FAERIE_SWARM);
                    SetNextPullSpellAllowed();
                    return RunStatus.Success;
                }
                if (gotTarget
                    && SpellManager.HasSpell(FAERIE_FIRE)
                    && !SpellManager.HasSpell(FAERIE_SWARM)
                    && GetSpellCooldown(FAERIE_FIRE).TotalSeconds < 1
                    && SpellManager.CanCast(FAERIE_FIRE)
                    && IsInRange(30, Me.CurrentTarget))
                {
                    SpellManager.Cast(FAERIE_FIRE);
                    Logging.Write(Colors.LightBlue, FAERIE_FIRE);
                    SetNextPullSpellAllowed();
                    return RunStatus.Success;
                }
                if (gotTarget 
                    && Me.Specialization == WoWSpec.DruidGuardian
                    && GetSpellCooldown(GROWL).TotalSeconds < 1 
                    && SpellManager.CanCast(GROWL)
                    && IsInRange(30, Me.CurrentTarget))
                {
                    SpellManager.Cast(GROWL);
                    Logging.Write(Colors.LightBlue, GROWL);
                    SetNextPullSpellAllowed();
                    return RunStatus.Success;
                }
                if (gotTarget
                    && Me.Specialization == WoWSpec.DruidFeral
                    && SpellManager.CanCast(RAKE)
                    && Me.CurrentTarget.IsWithinMeleeRange)
                {
                    SpellManager.Cast(RAKE);
                    Logging.Write(Colors.LightBlue, RAKE);
                    SetNextPullSpellAllowed();
                    return RunStatus.Success;
                }
                if (gotTarget
                    && GetSpellCooldown(MANGLE).TotalSeconds < 1
                    && SpellManager.CanCast(MANGLE)
                    && Me.CurrentTarget.IsWithinMeleeRange)
                {
                    SpellManager.Cast(MANGLE);
                    Logging.Write(Colors.LightBlue, MANGLE);
                    SetNextPullSpellAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region stun interrupt
        private DateTime nextInterruptAllowed;

        public void SetNextInterruptAllowed()
        {
            nextInterruptAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 2500);
        }

        private DateTime nextStunAllowed;

        public void SetNextNextStunAllowed()
        {
            nextStunAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 2500);
        }
        Composite WarStomp()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(WAR_STOMP))
                {
                    SpellManager.Cast(WAR_STOMP);
                    Logging.Write(Colors.Red, WAR_STOMP);
                    SetNextNextStunAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        Composite MightyBash()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(MIGHTY_BASH))
                {
                    SpellManager.Cast(MIGHTY_BASH);
                    Logging.Write(Colors.Red, MIGHTY_BASH);
                    SetNextNextStunAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        Composite SkullBash()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(SKULL_BASH))
                {
                    SpellManager.Cast(SKULL_BASH);
                    Logging.Write(Colors.Red, SKULL_BASH);
                    SetNextInterruptAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region lifeblood
        Composite LifeBlood()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(LIFEBLOOD))
                {
                    SpellManager.Cast(LIFEBLOOD);
                    Logging.Write(Colors.Orange, LIFEBLOOD);
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region NeedBearForm
        public bool NeedBearForm
        {
            get
            {
                if (!SpellManager.HasSpell(BEAR_FORM))
                {
                    return false;
                }
                if (SwitchBearForm || buffExists(MIGHT_OF_URSOC, Me))
                {
                    return true;
                }
                if (UnfriendlyUnits.Count() >= SettingsCat.myPrefs.startBearAoe
                    && !PauseAoe
                    && !Me.CurrentMap.IsInstance
                    && !Me.CurrentMap.IsDungeon
                    && !Me.CurrentMap.IsRaid
                    && !Me.GroupInfo.IsInRaid)
                {
                    return true;
                }
                return false;
            }
        }
        #endregion
    }
}
